package main

import (
	. "GO_data_structures_and_algorithms/tool"
	. "fmt"
)

//位运算加法的步骤
/*
1。a'=a,b无进位相加就是01得1 11得0 00得0的^异或运算
2.b'=再让a&b得出哪位进位了再让其<<1左移动一位
3.如果b'等于零就是表示无进位信息那a就是最终答案
4.如果有进位信息那a‘，b’作为ab再来一轮
*/
func add(a, b int) int {
	sum := a
	for b != 0 {
		//Print32(int64(a))
		//Print32(int64(b))
		//Print32(int64(a ^ b))
		sum = a ^ b //无进位相加
		//Print32(int64(a & b))
		//Print32(int64((a & b) << 1))
		b = (a & b) << 1
		a = sum

	}
	//Print32(int64(sum))
	return sum
}

func negNum(n int) int {
	return add(^n, 1)
	//转负数的经典方式按位取反再加1（因为不能直接用+所以用add代替+1）
}

func minus(a, b int) int {
	//a-b可以转换成将b弄成负的再相加就是减法了

	return add(a, negNum(b))
}
func IsNega(a int) bool {
	return a < 0

}
func multi(a, b int) int {
	flag := 0
	if b < 0 {
		//当b为负数时为了防止其符号位右移导致死循环这边得转成正数参与运算顺便记住这个负号到时候要补回去
		b = ^b + 1
		flag = 1
	}
	//a*b
	result := 0
	for b != 0 { //当b为零时代表所有位上都没1就可以结束循环了
		if b&1 == 1 {
			//如果b&1有结果就说明b第一位有1需要加上这次a的结果
			result = add(result, a)
		}
		//每次a左移，b右移
		a <<= 1
		b >>= 1
	}
	if flag == 1 { //当b为负数时返回补上符号
		return negNum(result)
	}

	return result

}

func div(a, b int) int {
	a1 := a
	b1 := b
	res := 0
	if a < 0 { //进行位运算触发首先要保证两个数为正数
		a1 = negNum(a)
	}
	if b < 0 {
		b1 = negNum(b)
	}
	//a/b=c
	for i := 63; i >= 0; i = minus(i, 1) {
		if (a1 >> i) >= b1 { //如果a右移后大于等于b1就说明最终的c在这位上有1
			res = add(res, 1<<i)  //res就加上这1<<i的数字代表c这位上有1
			a1 = minus(a1, b1<<i) //a1再减去b1往左移对应的内容
			//这样可以判断缩短a1之后缩短右移的位数后是否大于b1
			//然后慢慢缩短右移的位数
			//不减的话就会一直大于，之后每位都是1
		}
	}
	if IsNega(a) == IsNega(b) { //最后就是判断两个是否位负数
		return res //同时为正 或者同时为负
	} else { //直接返回正数
		return negNum(res) //反之加上负号
	}

}
func Newdiv(a, b int) int {
	if a == MinInt && b == MinInt { //两个都为系统最小值的话直接返回1
		return 1
	} else if b == MinInt { //如果b是最小数，b的绝对值是最大的所以结果不用想肯定等于0
		return 0
	} else if a == MinInt {
		if b == negNum(1) { //当a是系统最小值除以-1时等于系统最大值
			//这是约定俗成的规矩
			return MaxInt
		} else {
			//因为系统最小值的绝对值比系统最大值要大
			//所以不能直接放入div里面进行除
			//所以要除以一个数的话先让其加1再去相除
			//得出的结果再去*b看看和a差多少如果差值比b大要结果要+1
			//反之不加
			c := div(add(a, 1), b)
			e := minus(a, multi(c, b))
			return add(c, div(e, b))
		}
	} else {
		return div(a, b)
	}

}

func main() {
	//Println(add(46, 20))
	//Println(negNum(10))
	//Println("------")
	//Println(multi(10, -10))
	////Print32(-10)
	//Println(multi(-10, 10))
	////a := -10
	////a = ^a + 1
	////println(a)
	////Print32(a)
	////Print32(int64(a))
	//Println(div(127, 6))
	//Println(MaxInt)
	//Print32(MaxInt)
	Println(MinInt)
	//Print32(MinInt)
	Println(Newdiv(MinInt, 5))
	Println(MinInt / 5)
}
